import {PermissionInfo} from "../../User/Permission";
import {HostInfo} from "../../https_server";
/**
 * Created by Weizehua on 2017/1/19.
 */

export class RequestUserInfo {
    id: number;
    permissions: PermissionInfo;
    signature: string;
    nickname?: string;
    headUrl?: string;
    expiredDate: any;
}

export class RequestParam {
    [idx: string]: string;
}

export type HandlerParamType = StringConstructor|NumberConstructor|BooleanConstructor|ObjectConstructor|DateConstructor;
export type HandlerParamTypeOption = HandlerParamType|{[idx: string]: HandlerParamTypeOption}
    | (HandlerParamType|{[idx: string]: HandlerParamTypeOption})[];

export type HandlerValidatorsOption = {[idx: string]: Function|Function[]| HandlerValidatorsOption[] | HandlerValidatorsOption}

export interface FormalHandlerResponse {
    success: boolean,
    reason?: string
    [idx: string]: any;
}

export type HandlerResponseNormalTypes = string|boolean;
export type HandlerResponse = HandlerResponseNormalTypes|FormalHandlerResponse|Promise<HandlerResponseNormalTypes|FormalHandlerResponse>;

export interface HandlerType extends Function {
    (...args: (HostInfo|RequestUserInfo|RequestParam|any)[]): HandlerResponse;
}

export type SignParamType = true|{signature?: string, signatureKeys?: any}
    |{[idx: string]: SignParamType}
    |{[idx: string]: SignParamType}[]
export type SignParamTypeWithoutRootArray = {[idx: string]: SignParamType}

export async function ensureErrorMessage(_retv: HandlerResponse, _msg: HandlerResponse): Promise<any> {
    let retv = await formalHandlerReturn(_retv);
    retv.reason = retv.reason || (await formalHandlerReturn(_msg)).reason;
    return retv;
}

export async function combineErrorMessage(_errPrefix: HandlerResponse, _retv: HandlerResponse, _errSuffix?: HandlerResponse, seperator: string = ''): Promise<any> {
    let retv = await formalHandlerReturn(_retv);
    if (_errPrefix) {
        let err = await formalHandlerReturn(_errPrefix);
        retv.reason = err.reason + seperator + retv.reason;
    }
    if (_errSuffix) {
        let err = await formalHandlerReturn(_errSuffix);
        retv.reason = retv.reason + seperator + err.reason;
    }
    return retv;
}

export async function isHandlerSuccess(_retv: HandlerResponse, from?: Function|string): Promise<boolean> {
    let retv = await _retv;
    switch (typeof retv) {
        case 'string':
            return false;
        case 'boolean':
            return <boolean>retv;
        case 'object':
            return (<FormalHandlerResponse>retv).success;
        default:
            throw new Error(`Unknown return type(${retv}:${typeof retv}) from handler ${from && (from as Function).name || from}`);
    }
}

export async function formalHandlerReturn(retv: HandlerResponse, from?: Function): Promise<FormalHandlerResponse> {
    retv = await retv;
    switch (typeof retv) {
        case 'string':
            return {success: false, reason: <string>retv};
        case 'boolean':
            return {success: <boolean>retv};
        case 'object':
            return <FormalHandlerResponse>retv;
        default:
            throw new Error(`Unknown return type(${retv}:${typeof retv}) from handler ${from && from.name}`);
    }
}
